package cn.daniellee.plugin.se;

import cn.daniellee.plugin.se.command.ExpertCommand;
import cn.daniellee.plugin.se.component.ItemGenerator;
import cn.daniellee.plugin.se.component.PlaceholderHook;
import cn.daniellee.plugin.se.listener.MenuListener;
import cn.daniellee.plugin.se.listener.PlayerListener;
import cn.daniellee.plugin.se.runnable.GemRunnable;
import cn.daniellee.plugin.se.storage.MysqlStorage;
import cn.daniellee.plugin.se.storage.Storage;
import cn.daniellee.plugin.se.storage.StorageConverter;
import cn.daniellee.plugin.se.storage.YamlStorage;
import cn.daniellee.plugin.se.util.Utils;
import com.google.common.io.ByteArrayDataOutput;
import com.google.common.io.ByteStreams;
import me.clip.placeholderapi.PlaceholderAPI;
import me.clip.placeholderapi.expansion.PlaceholderExpansion;
import org.bukkit.Bukkit;
import org.bukkit.entity.Player;
import org.bukkit.plugin.java.JavaPlugin;
import org.bukkit.scheduler.BukkitTask;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class SurvivalExpert extends JavaPlugin {

	public static final int VERSION_NUMBER = Integer.parseInt(Utils.PACKAGE_VERSION.split("_")[1]);

	public static final int RANDOM_CALC_BASE = 10000;

	private static SurvivalExpert instance;

	private String prefix;

	private boolean bungeecord;

	private Storage storage;

	private BigDecimal battleBonusPercentage;

	private BigDecimal lifeBonusPercentage;

	private List<String> oreBlocks;

	private List<String> cropBlocks;

	private int orePointRange;

	private int cropPointRange;

	private Object placeholderHook;

	private BukkitTask gemRunnable;

	// 需要检查Age属性的方块
	public static Map<String, Integer> ageCheckBlock = new HashMap<>();

	public static Map<String, String> covertItemBlock = new HashMap<>();

	static {
		ageCheckBlock.put("NETHER_WARTS", 3);
		ageCheckBlock.put("CHORUS_FLOWER", 5);
		if (VERSION_NUMBER > 12) {
			ageCheckBlock.put("WHEAT", 7);
			ageCheckBlock.put("CARROTS", 7);
			ageCheckBlock.put("POTATOS", 7);
			ageCheckBlock.put("BEETROOTS", 3);
			ageCheckBlock.put("COCOA", 2);
			ageCheckBlock.put("SUGAR_CANE", 1);
			ageCheckBlock.put("BAMBOO", 1);
		} else { //LAGECY
			ageCheckBlock.put("CROPS", 7);
			ageCheckBlock.put("CARROT", 7);
			ageCheckBlock.put("POTATO", 7);
			ageCheckBlock.put("BEETROOT", 3);
			ageCheckBlock.put("COCOA", 8);
			ageCheckBlock.put("SUGAR_CANE_BLOCK", 1);
		}

		if (VERSION_NUMBER > 12) {
			covertItemBlock.put("CARROTS", "CARROT");
			covertItemBlock.put("POTATOS", "POTATO");
			covertItemBlock.put("BEETROOTS", "BEETROOT");
			covertItemBlock.put("COCOA", "COCOA_BEANS");
			covertItemBlock.put("NETHER_WARTS", "NETHER_WART");
		} else { //LAGECY
			covertItemBlock.put("CROPS", "WHEAT");
			covertItemBlock.put("CARROT", "CARROT_ITEM");
			covertItemBlock.put("POTATO", "POTATO_ITEM");
			covertItemBlock.put("BEETROOT_BLOCK", "BEETROOT");
			covertItemBlock.put("SUGAR_CANE_BLOCK", "SUGAR_CANE");
			covertItemBlock.put("COCOA", "LOG");
			covertItemBlock.put("NETHER_WARTS", "NETHER_STALK");
		}
	}

	public void onEnable(){
		instance = this;

		if (loadConfig()) {
			getLogger().info(" ");
			getLogger().info(">>>>>>>>>>>>>>>>>>>>>>>> SurvivalExpert Loaded <<<<<<<<<<<<<<<<<<<<<<<<");
			getLogger().info(">>>>> If you encounter any bugs, please contact author's QQ: 768318841 <<<<<");
			getLogger().info(" ");

			Bukkit.getPluginManager().registerEvents(new PlayerListener(), this);
			Bukkit.getPluginManager().registerEvents(new MenuListener(), this);

			Bukkit.getPluginCommand("survivalexpert").setExecutor(new ExpertCommand());

			bungeecord = Bukkit.getServer().spigot().getConfig().getBoolean("settings.bungeecord", false);

			if (bungeecord) this.getServer().getMessenger().registerOutgoingPluginChannel(this, "BungeeCord");

			gemRunnable = new GemRunnable().runTaskTimer(this, 0, 100);

			// 挂钩PlaceholderAPI
			if (Bukkit.getPluginManager().getPlugin("PlaceholderAPI") != null) {
				placeholderHook = new PlaceholderHook(this);
				((PlaceholderExpansion) placeholderHook).register();
				getLogger().info(" ");
				getLogger().info(">>>>>>>>>>>>>>>>>>>> Successfully hook to PlaceholderAPI <<<<<<<<<<<<<<<<<<<".replace("&", "§"));
				getLogger().info(" ");
			}
		}
	}

	public boolean loadConfig() {
		getLogger().info("[SurvivalExpert]Loading config...");
		if(!getDataFolder().exists()) getDataFolder().mkdirs();
		if (storage instanceof MysqlStorage) {
			((MysqlStorage) storage).close();
		}
		storage = getConfig().getBoolean("storage.mysql.use", false) ? new MysqlStorage() : new YamlStorage();
		if (storage.initialize()) {
			getLogger().info("[SurvivalExpert]Storage initialized.");
		} else {
			getLogger().info(" ");
			getLogger().info("[SurvivalExpert]Initializing data store failed, please edit the config and reload the plugin.".replace("&", "§"));
			getLogger().info(" ");
			Bukkit.getPluginManager().disablePlugin(this);
			return false;
		}
		if (getConfig().getBoolean("storage.mysql.use", false) && getConfig().getBoolean("storage.mysql.convert", false)) {
			YamlStorage yamlStorage = new YamlStorage();
			if (yamlStorage.initialize()) {
				StorageConverter converter = new StorageConverter((MysqlStorage) storage, yamlStorage);
				converter.execute();
				getConfig().set("storage.mysql.convert", false);
				saveConfig();
				getLogger().info("[SurvivalExpert]Successfully transferred Yaml data to Mysql.");
			} else {
				getLogger().info(" ");
				getLogger().info("[SurvivalExpert]Yaml data store initialization failed, data conversion canceled.".replace("&", "§"));
				getLogger().info(" ");
			}
		}
		prefix = "&7[&6" + getConfig().getString("prompt-prefix", "SurvivalExpert") + "&7] &3: &r";
		ItemGenerator.disableSkullLoad = getConfig().getBoolean("setting.disable-skull-load", false);
		battleBonusPercentage = new BigDecimal(getConfig().getDouble("gem.battle.bonus-percentage", 0.1));
		lifeBonusPercentage = new BigDecimal(getConfig().getDouble("gem.life.bonus-percentage", 0.1));
		oreBlocks = Arrays.asList(getConfig().getString("setting.ore.blocks", "COAL_ORE,IRON_ORE,GOLD_ORE,DIAMOND_ORE,EMERALD_ORE,LAPIS_ORE,REDSTONE_ORE,NETHER_QUARTZ_ORE").split(","));
		cropBlocks = Arrays.asList(getConfig().getString("setting.crop.blocks", "WHEAT,CARROTS,POTATOS,BEETROOTS,COCOA,NETHER_WARTS,CHORUS_FLOWER,SUGAR_CANE,PUMPKIN,MELON,CACTUS,BAMBOO").split(","));
		double orePointChange = getConfig().getDouble("setting.ore.chance", 1);
		if (orePointChange > 1 || orePointChange < 0.01) {
			getLogger().info("[SurvivalExpert]The chance can only be between 0.01 and 1, it is automatically set to 1.".replace("&", "§"));
			orePointChange = 1;
		}
		// 计算几率范围
		orePointRange = new BigDecimal(orePointChange).multiply(new BigDecimal(RANDOM_CALC_BASE)).intValue();
		double cropPointChange = getConfig().getDouble("setting.crop.chance", 1);
		if (cropPointChange > 1 || cropPointChange < 0.01) {
			getLogger().info("[SurvivalExpert]The chance can only be between 0.01 and 1, it is automatically set to 1.".replace("&", "§"));
			cropPointChange = 1;
		}
		cropPointRange = new BigDecimal(cropPointChange).multiply(new BigDecimal(RANDOM_CALC_BASE)).intValue();
		saveDefaultConfig();
		return true;
	}

	@Override
	public void onDisable() {
		if (bungeecord) this.getServer().getMessenger().unregisterOutgoingPluginChannel(this, "BungeeCord");

		if (gemRunnable != null && !gemRunnable.isCancelled()) {
			gemRunnable.cancel();
		}

		// 解挂PlaceholderAPI
		if (placeholderHook != null) {
			PlaceholderAPI.unregisterExpansion(((PlaceholderExpansion) placeholderHook));
			getLogger().info(" ");
			getLogger().info(">>>>>>>>>>>>>>>>>>>>>>>>>> Unhook to PlaceholderAPI <<<<<<<<<<<<<<<<<<<<<<<<<".replace("&", "§"));
			getLogger().info(" ");
		}

		getLogger().info(" ");
		getLogger().info(">>>>>>>>>>>>>>>>>>>>>>>> SurvivalExpert Unloaded <<<<<<<<<<<<<<<<<<<<<<<<");
		getLogger().info(" ");
	}

	public static SurvivalExpert getInstance() {
		return instance;
	}

	public void sendBroadcast(String broadcast) {
		if (bungeecord) {
			List<Player> players = (List<Player>) Bukkit.getOnlinePlayers();
			if (!players.isEmpty()) {
				ByteArrayDataOutput out = ByteStreams.newDataOutput();
				out.writeUTF("Message");
				out.writeUTF("ALL");
				out.writeUTF(broadcast);
				players.get(0).sendPluginMessage(this, "BungeeCord", out.toByteArray());
			}
		} else Bukkit.broadcastMessage(broadcast);
	}

	public String getPrefix() {
		return prefix;
	}

	public Storage getStorage() {
		return storage;
	}

	public BigDecimal getBattleBonusPercentage() {
		return battleBonusPercentage;
	}

	public BigDecimal getLifeBonusPercentage() {
		return lifeBonusPercentage;
	}

	public List<String> getOreBlocks() {
		return oreBlocks;
	}

	public List<String> getCropBlocks() {
		return cropBlocks;
	}

	public int getOrePointRange() {
		return orePointRange;
	}

	public int getCropPointRange() {
		return cropPointRange;
	}

}
